﻿using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Editor;
using Microsoft.VisualStudio.Text.Formatting;
using BasicallyNot.CodeTransformers.Handlers;
using BasicallyNot.CodeTransformers.Searchers;


namespace BasicallyNot.CodeTransformers.Transformers
{

	internal class VisualTransformer : BaseCodeTransformer
	{

		internal static LinkedList<Keyword> Keywords = new LinkedList<Keyword>();

		static VisualTransformer()
		{
			IVisualSearcher mustComeFirst = new MustComeFirst();
			IVisualSearcher containsValue = new ContainsValue();
			IVisualSearcher containsValueNotExit = new ContainsValue();

			IVisualHandler endBlock = new EndBlock();
			IVisualHandler beginBlock = new BeginBlock();
			IVisualHandler beginAndEndBlock = new BeginAndEndBlock();

			Keywords.AddLast( new Keyword( "End Namespace",		mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Module",			mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Structure",		mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Class",				mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Interface",		mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Enum",				mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Sub",					mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Function",		mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Property",		mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Get",					mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Set",					mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Select",			mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End If",					mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End While",				mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "Next",						mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "Loop",						mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Using",				mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End Try",					mustComeFirst,						endBlock ) );
			Keywords.AddLast( new Keyword( "End With",				mustComeFirst,						endBlock ) );
			
			Keywords.AddLast( new Keyword( "ElseIf",					mustComeFirst,						beginAndEndBlock ) );
			Keywords.AddLast( new Keyword( "Else",						mustComeFirst,						beginAndEndBlock ) );

			Keywords.AddLast( new Keyword( "Namespace",				containsValue,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Module",					containsValue,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Structure",				containsValue,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Class",						containsValue,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Interface",				containsValue,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Enum",						containsValue,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Sub",							containsValueNotExit,			beginBlock ) );
			Keywords.AddLast( new Keyword( "Function",				containsValueNotExit,			beginBlock ) );
			Keywords.AddLast( new Keyword( "Property",				containsValueNotExit,			beginBlock ) );
			Keywords.AddLast( new Keyword( "Get",							mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Set",							mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Select",					mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "If",							mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "ElseIf",					mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Else",						mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "For",							mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Do",							mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "While",						mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Using",						mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Try",							mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Catch",						mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "Finally",					mustComeFirst,						beginBlock ) );
			Keywords.AddLast( new Keyword( "With",						mustComeFirst,						beginBlock ) );
		}

		internal VisualTransformer( CodeTransformerManager manager )
			: base( manager )
		{
		}



		internal override bool Transform( ITextViewLine line )
		{
			string lineText = Manager.View.TextSnapshot.GetText( line.Start, line.Length ).ToLower();
			VisualSearcherEventArg searchArg = new VisualSearcherEventArg( lineText );
			VisualSearchResult searchResult = new VisualSearchResult();
			IVisualSearcher search;

			foreach ( Keyword keyword in Keywords ) {
				search = keyword.Searcher;
				searchArg.Keyword = keyword.Lower;
				search.Match( searchArg, ref searchResult );

				if ( searchResult.IsMatch ) {
					IVisualHandler handler = keyword.Handler;
					VisualHandlerEventArg handlerArg = new VisualHandlerEventArg( Manager, line, keyword, searchResult );
					handler.Handle( handlerArg );

					return true;
				}
			}

			// we did not find anything on this line
			return false;
		}

	}

}
